﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Linq;
using Microsoft.Deployment.WindowsInstaller.Package;

namespace MsiValidator
{
    public partial class MainForm : Form
    {
        private string msiFilePath = string.Empty;
        private string transformFilePath = string.Empty;
        private string RulesDir = Directory.GetCurrentDirectory() + "\\Rules";
        private bool isInternalCab = true;

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            //Populate Rules dropdown combobox
            if (Directory.Exists(RulesDir))
            {
                var files = Directory.EnumerateFiles(RulesDir).OrderByDescending(filename => filename);

                foreach (string file in files)
                {
                    toolStripRuleComboBox.Items.Add(Path.GetFileNameWithoutExtension(file));
                }
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox dlg = new AboutBox();
            dlg.ShowDialog();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openMsiFileDialog.ShowDialog() == DialogResult.OK)
            {
                msiFilePath = openMsiFileDialog.FileName;
                //checkedListBox1.Items.Clear();
                validationResultTreeView.Nodes.Clear();
                rulesTreeView.Nodes.Clear();
                toolStripStatusLabel.Text = msiFilePath + " was loaded.";
                //Reset transform
                transformFilePath = string.Empty;
                applyTransformToolStripMenuItem.Enabled = true;
                //Enable run button
                toolStripRunButton.Enabled = true;
            }
        }

        private void applyTransformToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openTransformFileDialog.ShowDialog() == DialogResult.OK)
            {
                transformFilePath = openTransformFileDialog.FileName;
                //checkedListBox1.Items.Clear();
                validationResultTreeView.Nodes.Clear();
                rulesTreeView.Nodes.Clear();
                toolStripStatusLabel.Text = transformFilePath + " was loaded.";
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void DisplayMessageBoxText(string e)
        {
            MessageBox.Show(e);
        }

        private void toolStripRunButton_Click(object sender, EventArgs e)
        {
            if (msiFilePath != "")
            {
                validationResultTreeView.Nodes.Clear();
                rulesTreeView.Nodes.Clear();

                TreeNode treeNode = new TreeNode(msiFilePath);
                rulesTreeView.Nodes.Add(treeNode);

                try
                {
                    /* 
                     * Linq to Msi
                     *
                    using (var database = new QDatabase(msiFilePath, DatabaseOpenMode.ReadOnly))
                    {
                        var properties = from p in database.Properties
                                         select p;

                        foreach (var property in properties)
                        {
                            Console.WriteLine("{0} = {1}", property.Property, property.Value);
                        }
                    }
                    */

                    using (Database database = new Database(msiFilePath, DatabaseOpenMode.ReadOnly))
                    {
                        if (transformFilePath != "")
                        {
                            database.ApplyTransform(transformFilePath, TransformErrors.None);
                            treeNode = new TreeNode(transformFilePath);
                            rulesTreeView.Nodes.Add(treeNode);
                        }

                        /*
                        using (var view = database.OpenView(database.Tables["Property"].SqlSelectString))
                        {
                            view.Execute();
                            foreach (var rec in view) using (rec)
                            {
                                Console.WriteLine("{0} = {1}", rec.GetString("Property"), rec.GetString("Value"));
                            }
                        }
                        */

                        string xmlRuleFile = @"Rules\" + toolStripRuleComboBox.SelectedItem + ".xml";
                        if (toolStripRuleComboBox.SelectedItem != null)
                        {
                            ReadXML.ReadRulesFromXmlFile(xmlRuleFile);
                        }

                        TreeNode node2 = new TreeNode("C#");
                        TreeNode node3 = new TreeNode("VB.NET");
                        TreeNode[] array = new TreeNode[] { node2, node3 };
                        //
                        // Final node.
                        //
                        treeNode = new TreeNode("Dot Net Perls", array);
                        rulesTreeView.Nodes.Add(treeNode);

                        var msg = MsiValidator.InsertProperties(database, "Property", "ALLUSERS", "1");
                        if (msg != null)
                        {
                            validationResultTreeView.Nodes.Add(msg);
                            msg = null;
                        }

                        msg = MsiValidator.InsertProperties(database, "Property", "ROOTDRIVE", "C:\\");
                        if (msg != null)
                        {
                            validationResultTreeView.Nodes.Add(msg);
                            msg = null;
                        }

                        msg = MsiValidator.InsertProperties(database, "Property", "REBOOT", "ReallySuppress");
                        if (msg != null)
                        {
                            validationResultTreeView.Nodes.Add(msg);
                            msg = null;
                        }

                        msg = MsiValidator.InsertProperties(database, "Property", "LIMITUI", "1");
                        if (msg != null)
                        {
                            validationResultTreeView.Nodes.Add(msg);
                            msg = null;
                        }

                        msg = MsiValidator.InsertProperties(database, "Property", "MSIRESTARTMANAGERCONTROL", "Disable");
                        if (msg != null)
                        {
                            validationResultTreeView.Nodes.Add(msg);
                            msg = null;
                        }

                        //for each rule
                        //var msg = MsiValidator.ExecuteRule(conn, "LaunchCondition", "MsiNTProductType=1", "This package is not intended for server installations");
                        //if ( msg != null)
                        //{
                        //    checkedListBox1.Items.Add(msg);
                        //    msg = null;
                        //}
                    }
                }
                catch (COMException COMex)
                {
                    DisplayMessageBoxText("Error " + COMex.ErrorCode.ToString() + ": " + COMex.Message);
                }
                catch (Exception err)
                {
                    DisplayMessageBoxText("Error: " + err.Message);
                }
            }
        }

        private void recompressWithCabInsideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (msiFilePath != "")
            {
                isInternalCab = true;
                try
                {
                    MsiValidator.Recompress(msiFilePath, isInternalCab);
                }
                catch (Exception err)
                {
                    DisplayMessageBoxText("Error: " + err.Message);
                }
            }
        }

        private void recompressWithCabOutsideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (msiFilePath != "")
            {
                isInternalCab = false;
                try
                {
                    MsiValidator.Recompress(msiFilePath, isInternalCab);
                }
                catch (Exception err)
                {
                    DisplayMessageBoxText("Error: " + err.Message);
                }
            }
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Options opt = new Options();
            opt.ShowDialog(); 
        }

        private void projectExplorerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (rulesTreeView.Visible == false)
            {
                rulesTreeView.Visible = true;
                splitContainer.Panel1.Show();
                splitContainer.Panel1Collapsed = false;
            }
            else
            {
                rulesTreeView.Visible = false;
                splitContainer.Panel1.Hide();
                splitContainer.Panel1Collapsed = true;
            }
        }

    }
}